package control

import (
	"hi-jvm/instructions/base"
	"hi-jvm/instructions/util"
	"hi-jvm/rtda"
)

/*
lookupswitch
<0-3 byte pad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
match-offset pairs...
*/
// Access jump table by key match and jump
type LOOKUP_SWITCH struct {
	defaultOffset int32		// 对应默认情况下执行跳转所需的字节码偏移量
	npairs        int32
	matchOffsets  []int32	// 一个类似map的结构。key为case， value为跳转偏移量
}

// lookupswitch指令码的后面有0-3个字节的padding，以保证defaultOffset在字节码中的地址是4的倍数
func (self *LOOKUP_SWITCH) FetchOperands(reader *util.BytecodeReader) {
	reader.SkipPadding()
	self.defaultOffset = reader.ReadInt32()
	self.npairs = reader.ReadInt32()
	self.matchOffsets = reader.ReadInt32s(self.npairs * 2)
}

/*
先从操作数栈中弹出一个int变量
用它查找matchOffsets， 看是否能找到匹配的key
如果能，则按照value给出的偏移量跳转
如果不能，则按照defaultOffset跳转
 */
func (self *LOOKUP_SWITCH) Execute(frame *rtda.Frame) {
	key := frame.OperandStack.PopInt()
	for i := int32(0); i < self.npairs*2; i += 2 {
		if self.matchOffsets[i] == key {
			offset := self.matchOffsets[i+1]
			base.Branch(frame, int(offset))
			return
		}
	}
	base.Branch(frame, int(self.defaultOffset))
}
